#include "camera.h"

Camera::Camera()
{
  tpv_ = Point(0, 0, 0);
  fpv_ = Point(0, 0, 0);
  fpv_dir_ = EAST;
  pan_ = Point(0, 0, 0);
  radius_ = 0.5f;
  aspect_ratio_ = 1.f;
  zoom_ = 1;
  phi_ = -45.f * kPi / 180.f;
  theta_ = 45.f * kPi / 180.f;
  view_ = SCENE_VIEW;
}

bool Camera::IsFpv() {
  return view_ == PLAYER_VIEW;
}

void Camera::SwitchCamera() {
  view_ = view_ == SCENE_VIEW ? PLAYER_VIEW : SCENE_VIEW;
}

void Camera::SetSceneCamera() {
  view_ = SCENE_VIEW;
}

void Camera::SetContent(Point center, float radius)
{
  tpv_ = center;
  radius_ = radius;
}

void Camera::SetPlayer(Point position, Direction dir)
{
  fpv_ = position;
  fpv_dir_ = dir;
}

void Camera::SetAspectRatio(float aspect_ratio)
{
  aspect_ratio_ = aspect_ratio;
}

void Camera::Zoom(float zoom_incr)
{
  zoom_ -= zoom_incr;
  if (zoom_ > 3.f) zoom_ = 3;
  else if (zoom_ < .01f) zoom_ = .01;
}

void Camera::Rotate(float phi_incr, float theta_incr)
{
  phi_ += phi_incr * kPi / 180.f;
  theta_ += theta_incr * kPi / 180.f;
//  // Avoids turning the scene upside down
//  if (theta_ > kPi / 1.99) {
//    theta_ = kPi / 1.99;
//  } else if (theta_ < -kPi / 1.99) {
//    theta_ = -kPi / 1.99;
//  }
}

void Camera::Pan(float x, float y)
{
//  pan_.x += x;
//  pan_.y += y;
  pan_.x += x*cos(phi_) + y*sin(theta_)*sin(phi_);
  pan_.y += y*cos(theta_);
  pan_.z += x*sin(phi_) - y*sin(theta_)*cos(phi_);
}

void Camera::Reset()
{
  pan_ = Point(0, 0, 0);
  phi_ = -45.f * kPi / 180.f;
  theta_ = 45.f * kPi / 180.f;
  zoom_ = 1;
}

//Point Camera::GetObs()
//{
//  // Deprecated
//  float x, y, z;
//  x = GetDistance() * cos(phi_) * fabs(cos(theta_)) + vrp_.x;
//  y = GetDistance() * sin(theta_) + vrp_.y;
//  z = GetDistance() * sin(phi_) * fabs(cos(theta_)) + vrp_.z;
//  return Point(x, y, z);
//}

Point Camera::GetVrp()
{
  if (view_ == SCENE_VIEW) {
    return tpv_;
  }
  else {
    return fpv_;
  }
}

Point Camera::GetPan()
{
  if (view_ == SCENE_VIEW) {
    return pan_;
  }
  else {
    return Point(0, 0, 0);
  }
}

float Camera::GetDistance()
{
  if (view_ == SCENE_VIEW) {
    return radius_ * 2.f;
  }
  else {
    return 0;
  }
}

float Camera::GetNear()
{
  if (view_ == SCENE_VIEW) {
    return GetDistance() - radius_;
  }
  else {
    return .1f;
  }
}

float Camera::GetFar()
{
  if (view_ == SCENE_VIEW) {
    return GetDistance() + radius_;
  }
  else {
    return radius_ * 2.f;
  }
}

float Camera::GetPhi()
{
  if (view_ == SCENE_VIEW) {
    return phi_ / kPi * 180.f;
  }
  else {
    // Camera by default is looking WEST
    return (fpv_dir_ + 1) * 90.f;
  }
}

float Camera::GetTheta()
{
  if (view_ == SCENE_VIEW) {
    return theta_ / kPi * 180.f;
  }
  else {
    return 0;
  }
}

float Camera::GetFOV()
{
  if (view_ == SCENE_VIEW) {
    float hfov = asin(radius_ / GetDistance());
    if (aspect_ratio_ < 1) {
      hfov = atan(tan(hfov) / aspect_ratio_);
    }
    float fov = (2.f * hfov / kPi * 180.f) * zoom_;
    if (fov < 1.f) return 1;
    if (fov > 179.f) return 179;
    return fov;
  }
  else {
    return 90;
  }
}

float Camera::GetAspectRatio()
{
  return aspect_ratio_;
}
